/**
 * Created by apple on 2017/7/29.
 */
var DBFactory = require('../db/mysql_db');
var async = require('async');
var UserMoneyDao = module.exports;
var Global = require('../global_var');
var Config = require('../config');
var taokeCooperate = require('../db/taoke_cooperate.json');
var cacheLib = require('../util/cache');

var commissionInfoCache = [cacheLib.create(30000, 100, false), cacheLib.create(30000, 100, false)];

function addCommissionInfoCache(appSid, account, type, info) {
    var key = appSid + ':' + account;
    var cache = commissionInfoCache[type];
    cache.set(key, info);
}
function findCommissionInfoCache(appSid, account, type) {
    var key = appSid + ':' + account;
    var cache = commissionInfoCache[type];
    var obj = cache.get(key);
    return obj;
}

UserMoneyDao.DEFAULT_COMMISSION_RATIO = Config.NEW_TAOCOMMISSION_RATIO;
if(Config.USUZ_COMPANY_ACCOUNT){
    setTimeout(function () {
        var companyCommissionInfo0 = [{account:Config.USUZ_COMPANY_ACCOUNT}];
        findRatioByBalanceInfo('usuz', companyCommissionInfo0, 0, function (err) {
            if(!err && companyCommissionInfo0.hasOwnProperty('taoCommissionRatio')){
                UserMoneyDao.DEFAULT_COMMISSION_RATIO[0] = companyCommissionInfo0.taoCommissionRatio;
            }
        })
        var companyCommissionInfo1 = [{account:Config.USUZ_COMPANY_ACCOUNT}];
        findRatioByBalanceInfo('usuz', companyCommissionInfo1, 1, function (err) {
            if(!err && companyCommissionInfo1.hasOwnProperty('taoCommissionRatio')){
                UserMoneyDao.DEFAULT_COMMISSION_RATIO[1] = companyCommissionInfo1.taoCommissionRatio;
            }
        })
    }, 100);
}

UserMoneyDao.balanceSubsidy = function (data,cb) {

    if(!data.waitBalanceInfos || data.waitBalanceInfos.length <= 0){//没有可结算的
        cb('无可结算数据');
        return;
    }
    data.balancedInfos = [];             //结算完的数组
    data.moneyEnoughInfos = [];          //余额够结算的数据
    data.depositEnoughInfos = [];        //押金够结算的数组
    data.refuseInfos = [];               //不可结算的数组，包括押金不够，结算人不在本平台的情况
    data.allUserInfos = [];              //付款人、收款人的信息，查出来的存放在这

    //先余额结算
    moneyBalanceSubsidy(data,function (err) {
        if(err){
            cb(null,moneyBalanceWrongParam(err,data));
            return;
        }

        //再押金结算
        depositBalanceSubsidy(data,function (err) {
            if(err){
                console.log('押金结算失败');
                cb(null,depositBalanceWrongParam(err,data));
                return;
            }

            //押金结算成功,把已结算、已余额结算、已押金结算、不可结算的数组信息一起返回
            cb(null,allBalanceParam(data));

        });

    });
}


//先余额结算
function moneyBalanceSubsidy (data,cb) {

    var waitBalanceInfos = data.waitBalanceInfos;
    var allUserUids = [];        //付款人、收款的uid
    var orderIds = [];           //传过来要结算的所有订单的id，根据此查是否已结算过
    waitBalanceInfos.forEach(function (subsidyInfo) {
        orderIds.push(subsidyInfo.id);
        if(allUserUids.indexOf(subsidyInfo.pay_uid) < 0) {
            allUserUids.push(subsidyInfo.pay_uid);
        }
        if(allUserUids.indexOf(subsidyInfo.receive_uid) < 0){
            allUserUids.push(subsidyInfo.receive_uid);
        }
    });

    DBFactory.getConnection(function (error, connection) {
        if (error) {
            cb(error);
            return;
        }
        async.waterfall([

            function (callback) {
                connection.beginTransaction(function (err) {
                    callback(err);
                });
            },

            //先查询是否结算过
            function (callback) {

                connection.query("SELECT order_id FROM user_money WHERE order_id IN ? AND app_sid = 'paodan' ", [[orderIds]], function (err, result) {
                    if (err) {
                        callback('补贴结算时查询用户余额记录表失败: ' + err);
                        return;
                    }

                    //如果不存在，则全部添加
                    if(!result || result.length <= 0){
                        callback(null,'继续');
                        return;
                    }


                    var deleteIndexs = [];
                    //如果存在则从数组中删除，并且加入已结算id的数组，最后一起post回去
                    for(var i=0; i<waitBalanceInfos.length; i++) {
                        var balanceInfo = waitBalanceInfos[i];
                        for(var j=0; j<result.length; j++){
                            var existsInfo = result[j];
                            if(balanceInfo.id == existsInfo.order_id){//把已经结算的
                                balanceInfo.balance_status = 13;
                                balanceInfo.comment = '结算完成';
                                data.balancedInfos.push(balanceInfo);
                                deleteIndexs.push(i);
                                break;
                            }
                        }
                    }
                    //将不可结算的删除
                    data.waitBalanceInfos = deleteArrWithIndexs(waitBalanceInfos,deleteIndexs);
                    waitBalanceInfos = data.waitBalanceInfos;

                    callback(null,'继续');

                });
            },

            //先判断余额是否充足
            function (res,callback) {

                connection.query('SELECT * FROM users WHERE uid IN ? ',[[allUserUids]], function (err, result) {
                    if (err) {
                        callback('补贴结算时查询用户余额表失败: ' + err);
                        return;
                    }

                    //全部加入不可结算数组
                    if(!result || result.length <= 0){
                        waitBalanceInfos.forEach(function (subsidyInfo) {//如果都查不到，说明所有结算的单子都不是本平台用户，直接打回
                            subsidyInfo.balance_status = 14;
                            subsidyInfo.comment = '非本平台用户';
                            data.refuseInfos.push(subsidyInfo);
                        });
                        callback('非本平台用户，不可结算');
                        return;
                    }

                    data.allUserInfos = result;

                    //这里要改成一减付款人，一增付款人。 增的放一个数组，减的放一个数组，记录放一个数组
                    //记录就是balanceInfo
                    var moneyLogs = [];

                    var deleteIndexs = [];


                    //按每条订单，手动结算        将够结算的数据加入 余额够结算数组，id加入已结算id数组
                    for(var i=0; i<waitBalanceInfos.length; i++) {
                        var balanceInfo = waitBalanceInfos[i];
                        //按每条订单信息去寻找收款人、付款人以及构造记录; 如果确定不可结算或结算完毕，则加入删除的数组，一会删除
                        if(moneyFindPayUid(data,balanceInfo,moneyLogs)) {
                            deleteIndexs.push(i);
                        }

                    }

                    //将不可结算和结算完毕的删除
                    data.waitBalanceInfos = deleteArrWithIndexs(waitBalanceInfos,deleteIndexs);

                    callback(null,moneyLogs);

                });
            },

            //余额够支付的先支付，都没有要用余额支付的直接跳下一步
            function (moneyLogs, callback) {
                if (!moneyLogs) {
                    callback('操作失败');
                    return;
                }

                //没有余额要支付的，跳下一步
                if(data.moneyEnoughInfos.length <= 0){
                    callback(null,'继续');
                    return;
                }


                //循环结算，牺牲效率,这里做余额的一减付款人，一增收款人，一记录(付款人、收款人变动记录一起做)
                moneyBalance(connection,data.moneyEnoughInfos,0,function (err,res) {
                    if(err){
                        callback(err,res);
                        return;
                    }

                    //一记录
                    connection.query('INSERT INTO user_money (`order_id`,`uid`,`original_money`,`money`,`app_sid`,`comment`,`sign`) VALUES ? ', [moneyLogs], function (err, result) {
                        if (err) {
                            callback('结算补贴时插入余额记录失败' + err);
                            return;
                        }

                        if(result.affectedRows > 0){
                            callback(null,'继续');
                            return;
                        }

                        callback('结算补贴时插入余额记录失败');

                    });

                });


            }

        ], function (err, res) {
            if (err) {
                connection.rollback(function () {
                    connection.release();
                    cb(err);
                });
            } else {
                connection.commit(function (e) {
                    if (e) {
                        connection.rollback(function () {
                            connection.release();
                            cb(e);
                        });
                    } else {
                        connection.release();
                        cb(null, res);
                    }
                });
            }
        });

    });
}


//                                          找付款人: (数据已在内部做变更，返回告知是否在待结算数组中删除即可)
// 1、未找到付款人（返回删除）                      2、找到付款人(继续)
//                              2.1、未找到收款人(返回删除)                      2.2、找到收款人(继续结算)
//                                                       2.2.1、余额不够结算(返回不删除)            2.2.2、余额够结算(去结算，并返回删除)
//return ：是否要删除该订单，true 删除，fasle 不删除，可继续待押金结算
function moneyFindPayUid(data,balanceInfo,moneyLogs) {

    for(var j=0; j<data.allUserInfos.length; j++){

        var payUserInfo = data.allUserInfos[j];

        if(payUserInfo.uid == balanceInfo.pay_uid){            //先找到付款人扣款

            return moneyFindReceiveUid(data,balanceInfo,payUserInfo,moneyLogs);

        }
    }

    balanceInfo.balance_status = 14;
    balanceInfo.comment = '订单有误，未查询到付款人';
    data.refuseInfos.push(balanceInfo);
    return true;

}

//2.2:余额够结算(继续找收款人)
//2.2.1:找到收款人(返回删除) 2.2.2:未找到收款人(返回删除)
function moneyFindReceiveUid(data,balanceInfo,payUserInfo,moneyLogs) {

    for(var k=0; k<data.allUserInfos.length; k++){

        var receiveUserInfo = data.allUserInfos[k];         //继续找收款人加款

        if(receiveUserInfo.uid == balanceInfo.receive_uid){ //找到收款人


            if(payUserInfo.money >= balanceInfo.total_subsidy) {//如果余额够就去结算

                var payOriginalMoney = payUserInfo.money;
                var receiveOriginalMoney = receiveUserInfo.money;
                payUserInfo.money = parseFloat(payUserInfo.money) - parseFloat(balanceInfo.total_subsidy);    //找到收款人后可以开始扣款
                receiveUserInfo.money = parseFloat(receiveUserInfo.money) + parseFloat(balanceInfo.total_subsidy);


                var payLog = [];
                var receiveLog = [];                        //创建两条余额变更记录
                payLog.push(balanceInfo.id);
                payLog.push(balanceInfo.pay_uid);
                payLog.push(payOriginalMoney);
                payLog.push(balanceInfo.total_subsidy);
                payLog.push('paodan');
                payLog.push('补贴结算扣款，收款用户: '); //收款用户慢点考虑
                payLog.push(1);

                receiveLog.push(balanceInfo.id);
                receiveLog.push(balanceInfo.receive_uid);
                receiveLog.push(receiveOriginalMoney);
                receiveLog.push(balanceInfo.total_subsidy);
                receiveLog.push('paodan');
                receiveLog.push('补贴结算');
                receiveLog.push(0);

                moneyLogs.push(payLog, receiveLog);            //将两条余额表更记录存起来，下面修改

                balanceInfo.balance_status = 13;
                balanceInfo.comment = '结算完成';

                balanceInfo.money = payUserInfo.money;
                data.moneyEnoughInfos.push(balanceInfo);           //加入余额够结算数组

                return true;

            }else {
                balanceInfo.money = payUserInfo.money;             //余额不够扣的记录下付款人余额，下面结算押金用
                return false;
            }

        }
    }

    balanceInfo.balance_status = 14;
    balanceInfo.comment = '订单有误，未查询到收款人';
    data.refuseInfos.push(balanceInfo);
    return true;

}




//押金结算
function depositBalanceSubsidy(data,cb) {

    var waitBalanceInfos = data.waitBalanceInfos;

    DBFactory.getConnection(function (error, connection) {
        if (error) {
            cb(error);
            return;
        }
        async.waterfall([

            function (callback) {
                connection.beginTransaction(function (err) {
                    callback(err);
                });
            },

            //查看可否用押金支付 （包括 余额+押金 可结算）
            function (callback) {

                if(waitBalanceInfos.length <= 0){//已没有待结算的，全部用余额结算完了,直接调下一步
                    callback(null,'继续');
                    return;
                }

                var payUids = [];
                waitBalanceInfos.forEach(function (subsidyInfo) {//加入前去重下.
                    if(payUids.indexOf(subsidyInfo.pay_uid) < 0) {
                        payUids.push(subsidyInfo.pay_uid);
                    }
                });

                connection.query("SELECT uid,lvl,account,vip_type,app_sid,vip_sid FROM user_vip WHERE uid IN ? AND app_sid = 'paodan' AND vip_sid = 'creditDeposit' ", [[payUids]], function (err, result) {
                    if (err) {
                        console.log(err);
                        callback(err);
                        return;
                    }


                    if(!result || result.length <= 0){ //如果查不到，说明剩下要结算的单子没有押金，加入不可结算数组，直接打回了。
                        waitBalanceInfos.forEach(function (subsidyInfo) {
                            subsidyInfo.balance_status = 14;
                            subsidyInfo.comment = '押金不足，无法结算';
                            data.refuseInfos.push(subsidyInfo);

                        });
                        callback('部分订单无法结算');
                        return;
                    }

                    var vipLogInfos = [];
                    var moneyLogs = [];

                    var deleteIndexs = [];

                    //查押金是否充足够结算    //这里待结算数组waitBalanceInfos中，都是余额不够结算的了,但有可能有剩余. balanceInfo.money是先前查的所剩余额
                    for(var i=0; i<waitBalanceInfos.length; i++){
                        var balanceInfo = waitBalanceInfos[i];

                        if(depositFindPayUid(result,data,balanceInfo,vipLogInfos,moneyLogs)) deleteIndexs.push(i);

                    }


                    //将不可结算和结算完毕的删除
                    data.waitBalanceInfos = deleteArrWithIndexs(waitBalanceInfos,deleteIndexs);

                    //继续去结算
                    var LogInfo = {
                        vipLogInfos: vipLogInfos,
                        moneyLogs: moneyLogs
                    }
                    callback(null,LogInfo);


                });
            },

            //押金和余额够支付的去结算
            function (LogInfo, callback) {
                if (!LogInfo) {
                    callback('操作失败');
                    return;
                }

                //没有押金要支付的，跳下一步
                if(data.depositEnoughInfos.length <= 0){
                    callback(null,'继续');
                    return;
                }



                //循环结算，牺牲效率,这里做押金一减，一增付款人余额，一减付款人余额，一增收款人，一记录(付款人、收款人变动记录一起做)
                moneyAndDepositBalance(connection,data.depositEnoughInfos,0,function (err) {
                    if(err){
                        callback(err);
                        return;
                    }

                    //一记录
                    connection.query('INSERT INTO vip_log (`seller_account`,`client_account`,`vip_name`,`vip_type`,`lvl`,`duration`,`cost`,`comment`,`price`,`app_sid`,`original_lvl`,`sign`,`vip_sid`) VALUES ? ', [LogInfo.vipLogInfos], function (err, result) {
                        if (err) {
                            console.log(err);
                            callback('结算补贴时插入会员记录失败' + err);
                            return;
                        }

                        if(!result || result.affectedRows <= 0){
                            callback('结算失败，记录会员表失败');
                            return;
                        }

                        connection.query('INSERT INTO user_money (`order_id`,`uid`,`original_money`,`money`,`app_sid`,`comment`,`sign`) VALUES ? ', [LogInfo.moneyLogs], function (err, result) {
                            if (err) {
                                callback('结算补贴时插入余额记录失败' + err);
                                return;
                            }

                            if(!result || result.affectedRows <= 0){
                                callback('结算失败，记录余额表失败');
                                return;
                            }

                            callback(null,'继续');


                        });


                    });

                });


            }

        ], function (err, res) {
            if (err) {
                connection.rollback(function () {
                    connection.release();
                    cb(err);
                });
            } else {
                connection.commit(function (e) {
                    if (e) {
                        connection.rollback(function () {
                            connection.release();
                            cb(e);
                        });
                    } else {
                        connection.release();
                        cb(null, res);
                    }
                });
            }
        });

    });

}


//押金结算，找付款人
function depositFindPayUid(result,data,balanceInfo,vipLogInfos,moneyLogs) {

    for(var i=0; i<result.length; i++){

        if(result[i].uid == balanceInfo.pay_uid){                              //找付款人

            return depositFindReceiveUid(data,balanceInfo,result[i],vipLogInfos,moneyLogs);

        }

    }

    balanceInfo.balance_status = 14;
    balanceInfo.comment = '订单有误，未查询到付款人';
    data.refuseInfos.push(balanceInfo);
    return true;

}

//押金结算，找收款人
function depositFindReceiveUid(data,balanceInfo,userVipInfo,vipLogInfos,moneyLogs) {

    for(var i=0; i<data.allUserInfos.length; i++){
        var userInfo = data.allUserInfos[i];

        if(userInfo.uid == balanceInfo.receive_uid) {                //找收款人

            if((balanceInfo.money+userVipInfo.lvl) >= balanceInfo.total_subsidy) {//如果押金+余额 还够结算,去结算


                var total_subsidy_deleteMoney = balanceInfo.total_subsidy;
                if (balanceInfo.money > 0) {
                    total_subsidy_deleteMoney = balanceInfo.total_subsidy - balanceInfo.money; //补贴扣完余额后还要付多少
                }
                //押金要扣整数（向上取整）,还要有一个押金转余额记录
                balanceInfo.reduceLvl = Math.ceil(total_subsidy_deleteMoney);//记录减少了多少押金

                //构造vip_log表记录，先将押金转为余额
                var vipLogInfo = [];
                //seller_account,client_account,vip_name,vip_type,lvl,duration,cost,comment,price,app_sid,original_lvl,sign,vip_sid
                vipLogInfo.push('srv');
                vipLogInfo.push(userVipInfo.account);
                vipLogInfo.push('补贴抵扣');
                vipLogInfo.push(userVipInfo.vip_type);
                vipLogInfo.push(balanceInfo.reduceLvl);
                vipLogInfo.push(0);
                vipLogInfo.push(0);
                vipLogInfo.push('补贴抵扣');
                vipLogInfo.push(0);
                vipLogInfo.push(userVipInfo.app_sid);
                vipLogInfo.push(userVipInfo.lvl);
                vipLogInfo.push(1);
                vipLogInfo.push(userVipInfo.vip_sid);

                vipLogInfos.push(vipLogInfo);

                //构造余额表记录 (三条，付款人一增、付款人一减，收款人一增)

                var payAddLog = [];
                var payReduceLog = [];
                var receiveLog = [];                        //创建三条余额变更记录

                payAddLog.push(balanceInfo.id);
                payAddLog.push(balanceInfo.pay_uid);
                payAddLog.push(balanceInfo.money);
                payAddLog.push(balanceInfo.reduceLvl);
                payAddLog.push('paodan');
                payAddLog.push('押金转换余额');
                payAddLog.push(0);

                payReduceLog.push(balanceInfo.id);
                payReduceLog.push(balanceInfo.pay_uid);
                payReduceLog.push(balanceInfo.money + balanceInfo.reduceLvl);
                payReduceLog.push(balanceInfo.total_subsidy);
                payReduceLog.push('paodan');
                payReduceLog.push('补贴结算扣款，收款用户: '); //收款用户慢点考虑
                payReduceLog.push(1);

                receiveLog.push(balanceInfo.id);
                receiveLog.push(balanceInfo.receive_uid);
                receiveLog.push(userInfo.money);
                receiveLog.push(balanceInfo.total_subsidy);
                receiveLog.push('paodan');
                receiveLog.push('补贴结算');
                receiveLog.push(0);

                moneyLogs.push(payAddLog, payReduceLog, receiveLog);

                balanceInfo.balance_status = 13;
                balanceInfo.comment = '结算完成';
                data.depositEnoughInfos.push(balanceInfo);
                return true;
            }else {
                return false;
            }
        }
    }


    balanceInfo.balance_status = 14;
    balanceInfo.comment = '订单有误，未查询到收款人';
    data.refuseInfos.push(balanceInfo);
    return true;

}



//循环做余额结算，一减一增
function moneyBalance(connection,moneyEnoughInfos,index,callback) {

    if(moneyEnoughInfos.length <= 0 || index >= moneyEnoughInfos.length){
        callback(null,null);
        return;
    }

    var balanceInfo = moneyEnoughInfos[index];
    connection.query('update users set money = money - ? where uid = ? ', [balanceInfo.total_subsidy, balanceInfo.pay_uid], function (err, result) {
        if (err) {
            callback('结算补贴时扣款失败' + err);
            return;
        }
        if (!result || result.affectedRows <= 0) {
            callback('扣款时失败');
            return;
        }

        //一增
        connection.query('update users set money = money + ? where uid = ? ', [balanceInfo.total_subsidy, balanceInfo.receive_uid], function (err, result) {
            if (err) {
                callback('结算补贴时增款失败' + err);
                return;
            }
            if (!result || result.affectedRows <= 0) {
                callback('增款时失败');
                return;
            }

            moneyBalance(connection,moneyEnoughInfos,++index,callback);
        });

    });

}


//循环做押金和余额结算 押金一减，余额一增；付款人余额一减，收款人余额一增
function moneyAndDepositBalance(connection,depositEnoughInfos,index,callback) {

    if(depositEnoughInfos.length <= 0 || index >= depositEnoughInfos.length){
        callback(null,null);
        return;
    }

    var balanceInfo = depositEnoughInfos[index];
    depositReduceAndMoneyAdd(connection,balanceInfo,function (err) {

        if(err){
            callback(err);
            return;
        }

        //一减付款人余额
        connection.query('UPDATE users SET money = money - ? WHERE uid = ?', [balanceInfo.total_subsidy, balanceInfo.pay_uid], function (err, result) {
            if (err) {
                callback('押金结算补贴时增款失败' + err);
                return;
            }
            if (!result || result.affectedRows <= 0) {
                callback('扣款时失败');
                return;
            }

            //一增收款人余额
            connection.query('UPDATE users SET money = money + ? WHERE uid = ?', [balanceInfo.total_subsidy, balanceInfo.receive_uid], function (err, result) {
                if (err) {
                    callback('押金结算补贴时增款失败' + err);
                    return;
                }
                if (!result || result.affectedRows <= 0) {
                    callback('增款时失败');
                    return;
                }

                moneyAndDepositBalance(connection,depositEnoughInfos,++index,callback);

            });

        });

    });


}



//扣押金，加余额
function depositReduceAndMoneyAdd(connection,balanceInfo,callback) {
    //一减付款人押金
    connection.query('UPDATE user_vip SET lvl = lvl - ? WHERE uid = ? AND app_sid = ? AND vip_sid = ? ', [balanceInfo.reduceLvl, balanceInfo.pay_uid,'paodan','creditDeposit'], function (err, result) {
        if (err) {
            callback('押金结算补贴时扣款失败' + err);
            return;
        }
        if (!result || result.affectedRows <= 0) {
            callback('扣款时失败');
            return;
        }

        //一增付款人余额
        connection.query('UPDATE users SET money = money + ? WHERE uid = ?', [balanceInfo.reduceLvl, balanceInfo.pay_uid], function (err, result) {
            if (err) {
                callback('押金结算补贴时增款失败' + err);
                return;
            }
            if (!result || result.affectedRows <= 0) {
                callback('增款时失败');
                return;
            }

            callback(null,'继续');

        });

    });

}


function baseParamInfo(err,data) {
    var param = {
        err: err,
        resultInfos: []
    }
    data.balancedInfos.forEach(function (balanceInfo) {
        param.resultInfos.push(balanceInfo);
    });
    data.refuseInfos.forEach(function (balanceInfo) {
        param.resultInfos.push(balanceInfo);
    });
    return param;
}

//余额结算出错时,返回的信息: 已经在用户中心结算过的，结算有误的
function moneyBalanceWrongParam(err,data) {
    return baseParamInfo(err,data);
}

//押金结算出错时,返回的信息: 已经在用户中心结算过的，结算有误的，余额结算完毕的
function depositBalanceWrongParam(err,data) {
    var param = moneyBalanceWrongParam(err,data);
    data.moneyEnoughInfos.forEach(function (balanceInfo) {
        param.resultInfos.push(balanceInfo);
    });
    return param;
}

//余额，押金结算完毕时，返回的信息: 已经在用户中心结算过的，结算有误的，余额结算完毕的， 剩余无法结算的归入结算有误的,押金结算完毕的,
function allBalanceParam(data) {
    var param = depositBalanceWrongParam(null,data);
    delete param.err;

    data.waitBalanceInfos.forEach(function (balanceInfo) {
        balanceInfo.balance_status = 14;
        balanceInfo.comment = '余额不足，无法结算';
        param.resultInfos.push(balanceInfo);
    });
    data.depositEnoughInfos.forEach(function (balanceInfo) {
        param.resultInfos.push(balanceInfo);
    });
    return param;
}



function deleteArrWithIndexs(deleteArr,deleteIndexs) {
    var newArr = [];
    for(var i=0; i<deleteArr.length; i++){
        if(deleteIndexs.indexOf(i) < 0){
            newArr.push(deleteArr[i]);
        }
    }
    deleteArr = newArr;
    return deleteArr;
}

//这里开始是usuz的结算------------
//usuz结算佣金
UserMoneyDao.balanceCommission = function (data,cb) {

    if(!data.waitBalanceArr || data.waitBalanceArr.length <= 0){//没有可结算的
        cb('无可结算数据');
        return;
    }
    balanceCommissionHandle(data,function (err) {
        //结算后发回usuz的参数 err为空时恰好传递的也是null
        cb(null,getParamWith(err,data));
    });

}

//具体操作数据库的
function balanceCommissionHandle(data,cb) {
    data.balancedInfos = [];             //结算完的数组
    var orderIds = [];
    var uids = [];
    data.month = (new Date()).getMonth() ;
    data.waitBalanceInfos = {}; //uid做key，放最后筛选后可结算的
    var waitFilterOrderIdInfo = {}; //order_id做key 待筛选的信息
    var waitFilterOrderUidInfo = {} //uid做key
    for (var i = 0; i < data.waitBalanceArr.length; i++) {//先筛选一遍待结算数据，金额过小的不结算了。
        var balanceInfo = data.waitBalanceArr[i];
        if(parseFloat(balanceInfo.commission) < 0.01) {
            balanceInfo.balance_status = 14;
            balanceInfo.comment = '结算金额有误';
            data.balancedInfos.push(balanceInfo);
            continue;
        }
        if(balanceInfo.hasOwnProperty('id')) orderIds.push('01' + balanceInfo.id);
        if(balanceInfo.hasOwnProperty('uid')) uids.push(balanceInfo.uid);
        waitFilterOrderUidInfo[balanceInfo.uid] = balanceInfo;
        waitFilterOrderIdInfo[balanceInfo.id] = balanceInfo;
    }
    if(orderIds.length <= 0 || uids.length <= 0){
        cb('结算信息有误');
        return;
    }
    DBFactory.getConnection(function (error, connection) {
        if (error) {
            cb(error);
            return;
        }
        async.waterfall([

            function (callback) {
                connection.beginTransaction(function (err) {
                    callback(err);
                });
            },
            //先查询传过来要结算的订单是否结算过以及用户信息，并剔除已结算的 和 用户信息异常的订单
            function (callback) {
                connection.query("SELECT order_id FROM order_id_app WHERE app_sid = ? AND order_id IN ? ", [data.app_key,[orderIds]], function (err, result) {

                    if (err) {
                        callback('佣金结算时查询用户余额记录表失败: ' + err);
                        return;
                    }

                    //结算过的订单信息
                    var balancedOrderInfo = (result && result.length > 0 ) ? result : [];
                    var sql = "SELECT u.money,u.uid,uv.uid as isVip,uae.no_w_of_r1,uae.no_w_of_r2,uae.no_jw_of_r1,uae.no_jw_of_r2,u.agent_2,u.account,u.agent_1,u.agent_2,u.agent_3,u.agent_4,u.agent_5,u.agent_6 " +
                        " FROM user_app_new_agent u LEFT JOIN user_vip uv ON u.uid = uv.uid AND uv.app_sid = ? " +
                        " LEFT JOIN user_app_exinfo uae ON uae.uid = u.uid and uae.app_sid = u.app_sid " +
                        " WHERE u.app_sid = ? AND u.uid IN ? GROUP BY u.uid ";
                    //顺便查用户会员信息，能查到拥有一个会员的就结算,取巧查会员是不是精英微淘客。 一种会员的不是，两种会员的就是精英微淘客
                    connection.query(sql,[data.app_key,data.app_key,[uids]],function (err,result) {
                        if(err){
                            callback('佣金结算时查询用户表失败: ' + err);
                            return;
                        }

                        var userInfos = (result && result.length > 0 ) ? result : [];

                        filterBanlanceInfo(data,balancedOrderInfo,waitFilterOrderIdInfo,waitFilterOrderUidInfo,userInfos,function (err,userMoneyLogs,freezeMoneyLogs) {
                            if(err) return callback(err);
                            data.userMoneyLogs = userMoneyLogs;
                            data.freezeMoneyLogs = freezeMoneyLogs;
                            callback(null,null);
                        })

                    });

                });

            },

            //筛选过后结算可结算信息,批量结算消费者自己的(包括修改余额，记录余额表、积分表), 如果消费者自己不是会员，跳过该消费者(改为也结算)
            function (res, callback) {

                //有可结算到余额的，结算
                updateUserScoreAndMoneyOrFreezeByData(data.selfBalanceMoneyInfos,false,connection,0,function (err) {
                    if(err) return callback(err);
                    //有可结算到冻结金额的，结算
                    updateUserScoreAndMoneyOrFreezeByData(data.selfBalanceFreezeInfos,true,connection,0,function (err) {
                        if(err) return callback(err);

                        callback(null,'继续结算');
                    })
                });

            },

            //结算完自己的，插入余额表和冻结表
            function (res, callback) {

                //记录到余额表
                insertUserMoney(data.userMoneyLogs,connection,function (err) {
                    if(err) return callback(err);
                    //记录到冻结金额表
                    insertFreezeMoney(data.freezeMoneyLogs,connection,function (err) {
                        if(err) return callback(err);
                        callback(null,'继续结算');
                    })
                });
            },

            //消费者结算完毕后，再结算推荐人的
            function (res,callback) {
                if(!res){
                    callback('结算异常');
                    return;
                }
                balanceRecommenderCommission(data,connection,8,function (err,result) {
                    if(err) return callback(err);

                    //没出错，说明结算完成，但推荐人有可能有分佣，有可能没有
                    for(var key in data.waitBalanceInfos){
                        var balanceInfo = data.waitBalanceInfos[key];
                        balanceInfo.balance_status = 13;
                        balanceInfo.comment = '结算完成';
                        data.balancedInfos.push(balanceInfo);
                    };
                    callback(null,'继续结算');
                });

            },

            function (res,callback) {
                if(!res){
                    callback();
                    return;
                }
                if(data.balancedOrderIds.length <= 0) return callback(null,'结算完成');
                //写入订单唯一表
                connection.query('INSERT INTO order_id_app (`order_id`,`app_sid`,`comment`) VALUES ? ', [data.balancedOrderIds], function (err, result) {
                    if (err) {
                        callback('佣金结算时记录至余额表失败: ' + err);
                        return;
                    }
                    if(result.affectedRows == data.balancedOrderIds.length) {
                        callback(null, '结算完成');
                    }else {
                        console.log('结算订单大于可结算订单');
                        callback('订单数量有误，结算异常');
                    }
                });
            }

        ], function (err, res) {
            if (err) {
                connection.rollback(function () {
                    connection.release();
                    cb(err);
                });
            } else {
                connection.commit(function (e) {
                    if (e) {
                        connection.rollback(function () {
                            connection.release();
                            cb(e);
                        });
                    } else {
                        connection.release();
                        cb(null, res);
                    }
                });
            }
        });

    });
}


//筛选结算订单信息
function filterBanlanceInfo(data,balancedOrderInfo,waitFilterOrderIdInfo,waitFilterOrderUidInfo,userInfos,cb) {

    //查询出不同用户对应的佣金比例
    findRatioByBalanceInfo('usuz', userInfos, 0, function (err) {
        if(err) return cb(err);


        //查询是否已经结算过,已结算过的删除
        deleteBalancedInfo(data,balancedOrderInfo,waitFilterOrderIdInfo,waitFilterOrderUidInfo);


        var userMoneyLogs = [];         //记录user_moeny表的信息
        var freezeMoneyLogs = [];
        data.waitBalanceUids =[]; //所有可结算的uid，后面查推荐人用
        data.balancedOrderIds = [];//所有可结算的order_id，结算过后记录唯一标识，防重复结算用
        data.selfBalanceMoneyInfos = {uids:[],app_sid:data.app_key}; //自己可结算到余额的数组
        data.selfBalanceFreezeInfos = {uids:[],app_sid:data.app_key}; //自己可结算到冻结金额的数组

        //到这里,waitFilterOrderUidInfo里筛掉金额有误，已经结算的
        makeBalanceInfo(data,userInfos,waitFilterOrderUidInfo,userMoneyLogs,freezeMoneyLogs);

        for(var key in waitFilterOrderUidInfo){
            if(!data.waitBalanceInfos[key]){
                var balanceInfo = waitFilterOrderUidInfo[key];
                balanceInfo.balance_status = 14;
                balanceInfo.comment = '结算失败，未找到该用户';
                data.balancedInfos.push(balanceInfo);
            }
        }

        if ((userMoneyLogs.length <= 0 && freezeMoneyLogs.length <= 0) || isEmptyObj(data.waitBalanceInfos)) {
            cb('无可结算信息');
            return;
        }

        cb(null,userMoneyLogs,freezeMoneyLogs);

    });

}

//删除已经结算过的订单:
//参数说明 data: routes带进来的总数据
// balancedOrderInfo: 已结算过的订单信息
// waitFilterOrderIdInfo: 等待筛选的订单信息，以orderId为key
// waitFilterOrderUidInfo: 等待筛选的订单信息，以uid为key
function deleteBalancedInfo(data,balancedOrderInfo,waitFilterOrderIdInfo,waitFilterOrderUidInfo) {
    //查询是否已经结算过,已结算过的删除
    for (var i = 0; i < balancedOrderInfo.length; i++) {

        var existsInfo = balancedOrderInfo[i];
        var balanceInfo = waitFilterOrderIdInfo[existsInfo.order_id];
        if (balanceInfo) {//把已经结算的
            balanceInfo.balance_status = 13;
            balanceInfo.comment = '结算完成';
            data.balancedInfos.push(balanceInfo);
            delete waitFilterOrderUidInfo[balanceInfo.uid];
        }
    }
}

//再查询用户是否存在我们的数据库,存在的可以加入待结算订单，同时构造佣金信息
//参数说明 data: routes带进来的总数据
//userInfos： 要结算用户的信息(数组)
//waitFilterOrderUidInfo :去除金额有误的信息，所剩余可结算的订单信息
function makeBalanceInfo(data,userInfos,waitFilterOrderUidInfo,userMoneyLogs,freezeMoneyLogs) {

    //再查询用户是否存在我们的数据库,存在的可以加入待结算的了
    for (var i = 0; i < userInfos.length; i++) {
        var userInfo = userInfos[i];
        var balanceInfo = waitFilterOrderUidInfo[userInfo.uid];
        if(balanceInfo){//说明存在，可以结算，构造下 用户余额的信息

            // var moneyLog = [];
            // moneyLog.push(balanceInfo.id);
            // moneyLog.push(balanceInfo.uid);
            // if(userInfo.isVip) moneyLog.push(userInfo.money);
            // moneyLog.push(balanceInfo.commission);
            // moneyLog.push(data.app_key);
            // moneyLog.push('个人消费奖励');

            //计算佣金
            getNewRatio(balanceInfo.count_day,userInfo.taoCommissionRatio);
            var money = balanceInfo.commission * userInfo.taoCommissionRatio.self;
            money *= getNewCoefficient(balanceInfo.count_day,userInfo.taoCommissionRatio.belong_account);//活动期间改比例系数增加的 5月7日
            if (money < 0.01) {
                balanceInfo.balance_status = 14;
                balanceInfo.comment = '结算失败，金额低于0.01';
                data.balancedInfos.push(balanceInfo);
                continue;
            }
            if (userInfo.taoCommissionRatio.self < 0 || userInfo.taoCommissionRatio.self > 1) {
                balanceInfo.balance_status = 14;
                balanceInfo.comment = '结算失败，佣金比例有误';
                data.balancedInfos.push(balanceInfo);
                continue;
            }

            balanceInfo.no_w_of_r1 = userInfo.no_w_of_r1 ? userInfo.no_w_of_r1 : 0;
            balanceInfo.no_w_of_r2 = userInfo.no_w_of_r2 ? userInfo.no_w_of_r2 : 0;
            balanceInfo.no_jw_of_r1 = userInfo.no_jw_of_r1 ? userInfo.no_jw_of_r1 : 0;
            balanceInfo.no_jw_of_r2 = userInfo.no_jw_of_r2 ? userInfo.no_jw_of_r2 : 0;
            balanceInfo.taoCommissionRatio = userInfo.taoCommissionRatio;



            var param = {
                order_id:balanceInfo.id,
                uid:balanceInfo.uid,
                original_money:userInfo.money,
                money:money,
                app_sid:data.app_key,
                comment:'个人消费奖励',
                // unfreeze_sid: userInfo.isVip ? null : 'wtk',
            }
            // if(userInfo.isVip){
                makeUpdateUserInfo(data.selfBalanceMoneyInfos,userMoneyLogs,param);
            // }else {
            //     makeUpdateUserInfo(data.selfBalanceFreezeInfos,freezeMoneyLogs,param);
            // }

            // if (userInfo.isVip){
            //     balanceInfo.isVip = true;
            //     moneyLog.push(0);
            //     data.selfBalanceMoneyInfos[balanceInfo.uid] = {money:balanceInfo.commission};
            //     data.selfBalanceMoneyInfos.uids.push(balanceInfo.uid);
            //     userMoneyLogs.push(moneyLog);
            // } else {
            //     moneyLog.push('wtk');
            //     data.selfBalanceFreezeInfos[balanceInfo.uid] = {money:balanceInfo.commission};
            //     data.selfBalanceFreezeInfos.uids.push(balanceInfo.uid);
            //     freezeMoneyLogs.push(moneyLog);
            // }

            data.waitBalanceInfos[balanceInfo.uid] = balanceInfo; //记录可结算信息
            data.waitBalanceUids.push(balanceInfo.uid);           //记录可结算uid

            var balancedOrderId = [];                             //记录可结算的log
            balancedOrderId.push('01' + balanceInfo.id);
            balancedOrderId.push(data.app_key);
            balancedOrderId.push('佣金结算');
            data.balancedOrderIds.push(balancedOrderId);
        }
    }
}

//参数说明   userInfos:已查询出对应用户的部分信息
function findRatioByBalanceInfo(appSid, userInfos, type, cb) {

    var accounts = [];
    var commissionInfos = {}; //筛选出所有的用户及其代理的账号，查询他们的比例
    var allInCache = true;
    userInfos.forEach(function (userInfo) {
        var ratioInfo = findCommissionInfoCache(appSid, userInfo.account, type);
        if(ratioInfo){
            userInfo.taoCommissionRatio = ratioInfo;
            return;
        }
        allInCache = false;
        ['account', 'agent_6', 'agent_5', 'agent_4', 'agent_3', 'agent_2', 'agent_1'].forEach(function (t) {
            if(userInfo[t]) commissionInfos[userInfo[t]] = 1;
        });
    });
    if(allInCache) { return cb(null);}

    // // //最后加入公司的账号
    // commissionInfos[Config.USUZ_COMPANY_ACCOUNT] = 1;
    for (var key in commissionInfos) {
        accounts.push(key);
    }
    var sql = 'SELECT * FROM app_commission_new_ratio WHERE app_sid = ? AND type = ? AND account IN ?; ';
    DBFactory.poolQuery(sql, [appSid, type, [accounts]],
        function () {
            cb('no collection');
        },
        function (err, result) {
            if (err) {
                console.log('SELECT app_commission_new_ratio ERR' + err);
                cb(err);
                return;
            }
            result.forEach(function (t) {
                commissionInfos[t.account] = t;
            });
            userInfos.forEach(function (userInfo) {
                if(!(['account', 'agent_6', 'agent_5', 'agent_4', 'agent_3', 'agent_2', 'agent_1' ].some(function (t) {
                        var acc = userInfo[t];
                        var commissionInfo = commissionInfos[acc];
                        if(commissionInfo && commissionInfo.hasOwnProperty('tax')){
                            userInfo.taoCommissionRatio = commissionInfo;
                            addCommissionInfoCache(appSid, userInfo.account, type, commissionInfo);
                            return true;
                        }
                        return false;
                    }))
                ){
                    userInfo.taoCommissionRatio = {};
                    var ntcr = Config.NEW_TAOCOMMISSION_RATIO[type];
                    for(var k in ntcr) userInfo.taoCommissionRatio[k] = ntcr[k];
                    addCommissionInfoCache(appSid, userInfo.account, type, userInfo.taoCommissionRatio);
                }
            });
            cb(null);
        }
    );
}
UserMoneyDao.findRatioByBalanceInfo = findRatioByBalanceInfo;

UserMoneyDao.getRatioByAccounts = function(appSid, allAccounts, type, cb){

    var ret = {};
    var toGetAgentAccs = [];
    allAccounts.forEach(function (acc) {
        var ratioInfo = findCommissionInfoCache(appSid, acc, type);
        if(ratioInfo){
            ret[acc] = {taoCommissionRatio:ratioInfo};
            return;
        }
        toGetAgentAccs.push(acc);
        // allInCache = false;
        // ['account', 'agent_6', 'agent_5', 'agent_4', 'agent_3', 'agent_2', 'agent_1', ].forEach(function (t) {
        //     if(userInfo[t]) commissionInfos[userInfo[t]] = 1;
        // });
    });
    if(toGetAgentAccs.length > 0){  //筛选出所有的用户及其代理的账号，查询他们的比例
        var sql = 'select * from user_app_new_agent where account in ( ? ) and app_sid = ? ';
        DBFactory.poolQuery(sql, [toGetAgentAccs, appSid],
            function () {
                cb('no collection');
            },
            function(err, userInfos) {
                if(err) {
                    cb(err);
                } else {
                    UserMoneyDao.findRatioByBalanceInfo(appSid, userInfos, type, function (error) {
                        if(error){
                            cb(error);
                            return;
                        }
                        userInfos.forEach(function (t) {
                            ret[t.account] = t;
                        });
                        cb(null,ret);
                    });
                }
        });
        return;
    }
    cb(null, ret);
};

//递归结算推荐人佣金,先计算1级，再计算2级。。。。
function balanceRecommenderCommission(data,connection,index,callback) {

    //查找推荐人，并计算获得的佣金。如果没有推荐人或佣金的，跳过。
    var findRecommenderSql;
    var value = [data.app_key];
    if(index >= 1 && index <= 6){
        findRecommenderSql = "SELECT uaa.uid,uaa.account,u.account as recommender_account,u.uid as recommender_uid,u.money as original_money FROM user_app_new_agent uaa " +
            "INNER JOIN user_app_new_agent u ON uaa.agent_" + index + " = u.account AND u.app_sid = ? " +
            "WHERE uaa.uid IN ? AND uaa.app_sid = ? ";
    }
    else if(index == 7 || index == 8){
        var recommanderName = index == 7 ? 'recommender' : 'recommender2';
        findRecommenderSql = "SELECT uaa.uid,uaa.account,u.account as recommender_account,u.uid as recommender_uid,u.money as original_money,count(uv.uid) as isVip,uv.vip_sid,u.pre_agent_lvl as r_pre_agent_lvl " +
            "FROM user_app_new_agent uaa INNER JOIN user_app_new_agent u ON uaa." + recommanderName + " = u.account AND u.app_sid = ? " +
            "LEFT JOIN user_vip uv ON uaa." + recommanderName + " = uv.account AND uv.app_sid = ? " +
            "WHERE uaa.uid IN ? AND uaa.app_sid = ? GROUP BY uaa.uid";
        value.push(data.app_key);
    }
    else{
        callback(null,true);
        return;
    }

    value.push([data.waitBalanceUids],data.app_key);
    //查找是否有该级推荐人
    connection.query(findRecommenderSql, value, function (err, result) {
        if (err) {
            console.log(err);
            callback('佣金结算时，查找'+ (index+1) + '级推荐人失败: ' + err);
            return;
        }

        if(!result || result.length <= 0){ //没有该级推荐人，直接调用下级
            balanceRecommenderCommission(data,connection,index - 1,callback);
            return;
        }

        //有则去结算分推荐人的佣金:
        var recommenderInfos = {};
        result.forEach(function (recommenderInfo) {
            recommenderInfos[recommenderInfo.uid] = recommenderInfo;
        });
        if (isEmptyObj(recommenderInfos)) {//如果没有，结算下一级
            balanceRecommenderCommission(data, connection, index - 1, callback);
            return;
        }
        handleRecommenderMoney(connection, data, recommenderInfos, index, function (err) {
            if (err) return callback(err);//有错结束返回
            //没错递归调用
            balanceRecommenderCommission(data, connection, index - 1, callback);

        });
    });
}

//算好以后，结算推荐人的佣金的具体数据库操作，到这里的推荐人，肯定都是vip
function handleRecommenderMoney(connection,data,recommenderInfos,index,callback) {

    var userMoneyLogs = [];
    var freezeMoneyLogs = [];
    var updateUserInfo = getBaseUpdateUserInfo(data.app_key);
    var freezeMoneyInfo = getBaseUpdateUserInfo(data.app_key);


    for(var key in data.waitBalanceInfos) {
        var balanceInfo = data.waitBalanceInfos[key];
        var recommenderInfo = recommenderInfos[balanceInfo.uid];
        if(recommenderInfo){//根据订单找到推荐人，则结算

            //计算佣金
            calculateMoneyBy(recommenderInfo,balanceInfo,index);
            if (parseFloat(recommenderInfo.money) < 0.01) continue;

            var unfreeze_sid = null;
            // if (index > 6) {
            //     var isWTK = (!recommenderInfo.r_pre_agent_lvl && recommenderInfo.isVip == 1 && recommenderInfo.vip_sid != 'firstVip');
            //     var isWTKBeyond = index == 7 ? balanceInfo.no_w_of_r1 > 100 : balanceInfo.no_w_of_r2 > 100;
            //     var isJWTKByond = index == 7 ? balanceInfo.no_jw_of_r1 > 5 : balanceInfo.no_jw_of_r2 > 5;
            //     if (!recommenderInfo.isVip) unfreeze_sid = 'wtk'; //普通用户
            //     if (isWTK && isWTKBeyond) unfreeze_sid = 'wtk_limit'; //会员微淘客
            //     if (isWTK && isJWTKByond) unfreeze_sid = 'jwtk_limit';
            // }
            var param = {
                order_id:balanceInfo.id,
                uid:recommenderInfo.recommender_uid,
                original_money:recommenderInfo.original_money,
                money:parseFloat(recommenderInfo.money),
                app_sid:data.app_key,
                comment:getMoneyComment(index, recommenderInfo.account) + ' 消费返还结算',
                unfreeze_sid: unfreeze_sid,
            }
            if(!unfreeze_sid) {
                makeUpdateUserInfo(updateUserInfo,userMoneyLogs,param);
            }else {
                makeUpdateUserInfo(freezeMoneyInfo,freezeMoneyLogs,param);
            }
            // //构造余额或冻结金额记录
            // if(!updateUserInfo[recommenderInfo.recommender_uid]){
            //     updateUserInfo[recommenderInfo.recommender_uid] = {money:parseFloat(recommenderInfo.money),original_money:recommenderInfo.original_money};
            //     updateUserInfo.uids.push(recommenderInfo.recommender_uid);
            // }else {
            //     updateUserInfo[recommenderInfo.recommender_uid].money += parseFloat(recommenderInfo.money);
            // }
            //
            //
            // var moneyLog = [];
            // moneyLog.push(balanceInfo.id);
            // moneyLog.push(recommenderInfo.recommender_uid);
            // moneyLog.push(updateUserInfo[recommenderInfo.recommender_uid].original_money);
            // moneyLog.push(recommenderInfo.money);
            // moneyLog.push(data.app_key);
            // moneyLog.push(getMoneyComment(index, recommenderInfo.account) + ' 消费返还结算');
            // moneyLog.push(0);
            // userMoneyLogs.push(moneyLog);
            //
            // updateUserInfo[recommenderInfo.recommender_uid].original_money += parseFloat(recommenderInfo.money);//原金额要提高，防止多人同推荐人情况

        }

    }

    if(updateUserInfo.uids.length <= 0 && freezeMoneyInfo.uids.length <= 0){//没有找到要结算的推荐人，回去
        callback(null,null);
        return;
    }
    updateUserScoreAndMoneyOrFreezeByData(updateUserInfo,false,connection,0,function (err) {
        if(err) return callback(err);
        updateUserScoreAndMoneyOrFreezeByData(freezeMoneyInfo,true,connection,0,function (err) {
            if(err) return callback(err);
            insertUserMoney(userMoneyLogs,connection,function (err) {
                if(err) return callback(err);
                insertFreezeMoney(freezeMoneyLogs,connection,callback);
            });
        });
    });
}

//计算佣金
function calculateMoneyBy(recommenderInfo,balanceInfo,index) {

    var originalCommission = parseFloat(balanceInfo.commission);
    var commissionRate = 0;
    getNewRatio(balanceInfo.count_day,balanceInfo.taoCommissionRatio);
    if(index == 7){//直接推荐人
        commissionRate = balanceInfo.taoCommissionRatio.reference1;
    }
    else if(index == 8){//间接推荐人
        commissionRate = balanceInfo.taoCommissionRatio.reference2;
    }
    else if(index >= 1 && index <= 6){
        commissionRate = balanceInfo.taoCommissionRatio['agent_' + index];
    }

    //* (1-commissionRatio) 平台所得
    //* data.commission_rate1    推荐人所得
    //1、消费者如果是普通用户，佣金60%再分给上级(不分了)
    // recommenderInfo.money = balanceInfo.isVip ? parseFloat((balanceInfo.commission / OriginalRatio) * commissionRate).toFixed(2) :
    // parseFloat((balanceInfo.commission / OriginalRatio) * (commissionRate + commonCommissionRate)).toFixed(2);
    recommenderInfo.money = originalCommission * commissionRate;
    recommenderInfo.money *= getNewCoefficient(balanceInfo.count_day,balanceInfo.taoCommissionRatio.belong_account);//活动期间多加乘系数5月7日
    //2、推荐人如果是精英微淘客，多得1%，并且再结算人中记录下，待会儿结算区代的时候扣,后改为省代扣
    if ((index == 7 || index == 8) && recommenderInfo.vip_sid == 'firstVip' && Config.isSpecialElite(balanceInfo.taoCommissionRatio)) {
        var totalMoney = Config.specialMoneyElite(recommenderInfo.money, originalCommission, balanceInfo.taoCommissionRatio);
        // if(!balanceInfo.hasOwnProperty('rcm_elite_num')) balanceInfo.rcm_elite_num = 0;
        // balanceInfo.rcm_elite_num += totalMoney - recommenderInfo.money;
        recommenderInfo.money = totalMoney;
    }

    //3、如果推荐人有精英微淘客，区代扣除相应数量的比例金额，最多扣2,改为从省代中扣
    // if (index == 2 && balanceInfo.hasOwnProperty('rcm_elite_num')) {
    //     recommenderInfo.money -=  balanceInfo.rcm_elite_num;
    // }
    //如果推荐人是市场部，再对半结算
    var isNeedHalfObj = isNeedHalf(recommenderInfo.recommender_uid);
    if (isNeedHalfObj.isNeedHalf) {
        recommenderInfo.money *= isNeedHalfObj.commission_ratio;
    }
    recommenderInfo.money = parseFloat(recommenderInfo.money).toFixed(2);

}

//市场部，佣金部分是对半分,判断是否是市场部
function isNeedHalf(uid) {
    var res = {isNeedHalf:false}
    for(var key in taokeCooperate){
        var taokeInfo = taokeCooperate[key];
        if (taokeInfo.uid == uid){
            res.isNeedHalf = true;
            res.commission_ratio = taokeInfo.commission_ratio;
        }
    }
    return res;
}

function getBaseUpdateUserInfo(app_sid) {
    var updateUserInfo = {uids:[],app_sid:app_sid};
    return updateUserInfo;
}

//需要的参数data:{order_id,uid,original_money,money,app_sid,comment,unfreeze_sid}
function makeUpdateUserInfo(updateUserInfo,userMoneyLogs,param) {

    //构造余额或冻结金额记录
    if(!updateUserInfo[param.uid]){
        updateUserInfo[param.uid] = {money:parseFloat(param.money),original_money:param.original_money ? parseFloat(param.original_money) : 0};
        updateUserInfo.uids.push(param.uid);
    }else {
        updateUserInfo[param.uid].money += parseFloat(param.money);
    }

    var moneyLog = [];
    moneyLog.push('01' + param.order_id);
    moneyLog.push(param.uid);
    if(!param.unfreeze_sid) moneyLog.push(updateUserInfo[param.uid].original_money);
    moneyLog.push(param.money);
    moneyLog.push(param.app_sid);
    moneyLog.push(param.comment);
    if(!param.unfreeze_sid){
        moneyLog.push(0);
    } else {
        moneyLog.push(param.unfreeze_sid);
    }
    if (!param.unfreeze_sid) moneyLog.push(17);
    userMoneyLogs.push(moneyLog);

    updateUserInfo[param.uid].original_money += parseFloat(param.money);//原金额要提高，防止多人同推荐人情况

}



//循环结算用户积分、余额（或冻结金额）updateUserInfo结构：
//{ uids:[],app_sid:,
//  4:{
//        money:2
//    }
// }
function updateUserScoreAndMoneyOrFreezeByData(updateUserInfo,isFreeze,connection,index,callback) {
    if(index >= updateUserInfo.uids.length){
        callback(null,null);
        return;
    }
    var updateUid = updateUserInfo.uids[index];
    var updateUser = updateUserInfo[updateUid];
    var sql = 'UPDATE user_app_new_agent SET score = score + ? ';
    sql += isFreeze ? ' ,freeze_money = freeze_money + ? ' : ' ,money = money + ? ';
    sql += ' WHERE uid = ? AND app_sid = ? ';
    connection.query(sql, [updateUser.money,updateUser.money,updateUid,updateUserInfo.app_sid], function (err, result) {//结算积分
        if (err) {
            callback('结算时修改用户信息ERR: ' + err);
            console.log('结算时UPDATE user_app_new_agent ERR:' + err);
            return;
        }
        if(result.affectedRows <= 0){
            callback('结算时修改用户信息ERR: ' + err);
            console.log('结算时UPDATE user_app_new_agent affectedRows<=0:' + err);
            return;
        }
        updateUserScoreAndMoneyOrFreezeByData(updateUserInfo,isFreeze,connection,index + 1,callback);
    });
}


//插入余额记录表
function insertUserMoney(userMoneyLogs,connection,callback) {
    if(userMoneyLogs.length <= 0) return callback(null,null);
    connection.query('INSERT INTO user_money (`order_id`,`uid`,`original_money`,`money`,`app_sid`,`comment`,`sign`,`type`) VALUES ? ', [userMoneyLogs], function (err, result) {
        if (err) {
            callback('推荐人佣金结算时记录至余额表失败: ' + err);
            return;
        }
        if(result.affectedRows <= 0){
            callback('推荐人佣金结算时，结算数据条数有误，请检查: ');
            return;
        }
        callback(null,null);
    });
}

//插入冻结金额记录表
function insertFreezeMoney(freezeMoneyLogs,connection,callback) {
    if(freezeMoneyLogs.length <= 0) return callback(null,null);
    connection.query('INSERT INTO freeze_money_record (`order_id`,`uid`,`money`,`app_sid`,`comment`,`unfreeze_sid`) VALUES ? ', [freezeMoneyLogs], function (err, result) {
        if (err) {
            callback('推荐人佣金结算时记录至余额表失败: ' + err);
            return;
        }
        if(result.affectedRows <= 0){
            callback('推荐人佣金结算时，结算数据条数有误，请检查: ');
            return;
        }
        callback(null,null);
    });
}

//获取下级、下下级。。。被推荐人名称
function getMoneyComment(index,account) {
    const userInfo = account.length >= 11 ?  account.substr(0,3) + '****' + account.substr(7,4) : '';
    switch (index){
        case 8:{
            return '间接推荐收益：用户' + userInfo ;
            break;
        }
        case 7:{
            return '直接推荐收益：用户' + userInfo;
            break;
        }
        case 1:{
            return '总部收益：用户' + userInfo;
            break;
        }
        case 2:{
            return '分公司收益：用户' + userInfo;
            break;
        }
        case 3:{
            return '分公司管理组收益：用户' + userInfo;
            break;
        }
        case 4:{
            return '服务商收益：用户' + userInfo;
            break;
        }
        case 5:{
            return '服务商管理组收益: 用户' + userInfo;
            break;
        }
        case 6:{
            return '总监收益: 用户' + userInfo;
            break;
        }

    }
}

//构造佣金返回参数
function getParamWith(err,data) {
    var param = {
        err:err,
        resultInfos:data.balancedInfos,
    }
    return param;
}



UserMoneyDao.getMoneyList = function (data,cb) {

    if (!data) return cb(new Error(500));
    var sqlCount = 'SELECT COUNT(*) AS total FROM user_money WHERE  ';
    var sql = 'SELECT * FROM user_money WHERE ';
    var baseSql = ' uid = ? AND app_sid = ? ';
    var value = [data.uid,data.app_sid];
    if (data.type) {
        baseSql += ' AND type = ? ';
        value.push(data.type);
    }
    sqlCount += baseSql;
    sql += baseSql;
    sql += ' ORDER BY created_time DESC ';
    var pageSize = data.pageSize ? data.pageSize : 10;
    var page = data.page ? data.page : 1;
    sql += 'LIMIT ' + (page - 1) * pageSize + ',' + pageSize;
    DBFactory.poolQuery(sqlCount, value,
        function () {
            cb('no collection');
        },
        function (err, result,connection) {
            if (err) {
                console.log(err);
                cb(err);
                return;
            }
            var res = {
                total:0,
                moneyList:[],
            };
            if (!result || result.length <= 0) {
                cb(null,res);
                return;
            }
            res.total = result[0].total;
            connection.query(sql,value,function (err1,result1) {
                connection.release();
                if (err1) {
                    cb(err1);
                    return;
                }
                res.moneyList = result1;
                cb(null,res);
            });
            return true;
        }
    );

}

//获取活动期间修改比例的系数
function getNewCoefficient(count_day,belong_account) {
    var coefficient = 1;
    if (count_day >= Config.TIME_COMMISSION_COEFFICIENT.time1 && (!belong_account || belong_account == Config.USUZ_COMPANY_ACCOUNT)){
        coefficient = Config.TIME_COMMISSION_COEFFICIENT.coefficient1;
    }
    if (count_day >= Config.TIME_COMMISSION_COEFFICIENT.time2){
        coefficient = 1;
    }
    return coefficient;
}

//2018.10.17，修改比例
function getNewRatio(count_day,taoCommissionRatio) {
    var belong_account = taoCommissionRatio.belong_account;
    if (count_day < '2018-10-17' && (!belong_account || belong_account == Config.USUZ_COMPANY_ACCOUNT)) {
        taoCommissionRatio.self = 0.50;
        taoCommissionRatio.reference1 = 0.1;
        taoCommissionRatio.reference2 = 0;
        taoCommissionRatio.agent_6 = 0.09;
        taoCommissionRatio.agent_4 = 0.08;
        taoCommissionRatio.agent_2 = 0.05;
    }
}

UserMoneyDao.record = function(data, cb) {
    var param = {
        par:data,
        findKeysObj:{
            app_sid:{
                tableName:'um'
            },
            account:{
                tableName:'u'
            },
            type:{
                tableName:'um'
            }
        },
        findKeys: ['app_sid', 'account', 'type'],
        selectStr: 'um.*,u.account',
        fromStr: 'user_money um left join users u on um.uid = u.uid ',
        DBFactory:DBFactory,
        page:data.page ? data.page : 1,
        pageSize:data.pageSize ? data.pageSize : 10,
        startTime:data.start_time,
        endTime:data.end_time,
        timeKey:'created_time',
        orderByObj:{
            orderKey:'created_time',
            orderSort:'desc',
        }
    };
    dbBaseList(param,cb);
}
